Micron Document
๐ŸŽ–๏ธGitะฏั€ะฐ๐ŸŽ–๏ธ


Displaying Raw โ€ข Download

desktopApp/src/main/kotlin/org/meshtastic/desktop/Main.kt 4d4070c8e1ed73a56ee2f054300a0f62e3fe2e62 (4d4070c8) Text, 20.11 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.desktop

Tff7b72import T7ee787androidx.compose.foundation.isSystemInDarkTheme
Tff7b72import T7ee787androidx.compose.runtime.Composable
Tff7b72import T7ee787androidx.compose.runtime.CompositionLocalProvider
Tff7b72import T7ee787androidx.compose.runtime.DisposableEffect
Tff7b72import T7ee787androidx.compose.runtime.LaunchedEffect
Tff7b72import T7ee787androidx.compose.runtime.collectAsState
Tff7b72import T7ee787androidx.compose.runtime.getValue
Tff7b72import T7ee787androidx.compose.runtime.mutableStateOf
Tff7b72import T7ee787androidx.compose.runtime.produceState
Tff7b72import T7ee787androidx.compose.runtime.remember
Tff7b72import T7ee787androidx.compose.runtime.setValue
Tff7b72import T7ee787androidx.compose.runtime.snapshotFlow
Tff7b72import T7ee787androidx.compose.ui.Alignment
Tff7b72import T7ee787androidx.compose.ui.graphics.painter.Painter
Tff7b72import T7ee787androidx.compose.ui.input.key.Key
Tff7b72import T7ee787androidx.compose.ui.input.key.KeyEvent
Tff7b72import T7ee787androidx.compose.ui.input.key.KeyEventType
Tff7b72import T7ee787androidx.compose.ui.input.key.isAltPressed
Tff7b72import T7ee787androidx.compose.ui.input.key.isCtrlPressed
Tff7b72import T7ee787androidx.compose.ui.input.key.isMetaPressed
Tff7b72import T7ee787androidx.compose.ui.input.key.key
Tff7b72import T7ee787androidx.compose.ui.input.key.type
Tff7b72import T7ee787androidx.compose.ui.platform.LocalDensity
Tff7b72import T7ee787androidx.compose.ui.unit.Density
Tff7b72import T7ee787androidx.compose.ui.unit.DpSize
Tff7b72import T7ee787androidx.compose.ui.unit.dp
Tff7b72import T7ee787androidx.compose.ui.window.ApplicationScope
Tff7b72import T7ee787androidx.compose.ui.window.Tray
Tff7b72import T7ee787androidx.compose.ui.window.Window
Tff7b72import T7ee787androidx.compose.ui.window.WindowPosition
Tff7b72import T7ee787androidx.compose.ui.window.WindowState
Tff7b72import T7ee787androidx.compose.ui.window.application
Tff7b72import T7ee787androidx.compose.ui.window.isTraySupported
Tff7b72import T7ee787androidx.compose.ui.window.rememberTrayState
Tff7b72import T7ee787androidx.compose.ui.window.rememberWindowState
Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787co.touchlab.kermit.platformLogWriter
Tff7b72import T7ee787coil3.ImageLoader
Tff7b72import T7ee787coil3.annotation.ExperimentalCoilApi
Tff7b72import T7ee787coil3.compose.setSingletonImageLoaderFactory
Tff7b72import T7ee787coil3.disk.DiskCache
Tff7b72import T7ee787coil3.memory.MemoryCache
Tff7b72import T7ee787coil3.network.DeDupeConcurrentRequestStrategy
Tff7b72import T7ee787coil3.network.ktor3.KtorNetworkFetcherFactory
Tff7b72import T7ee787coil3.request.crossfade
Tff7b72import T7ee787coil3.svg.SvgDecoder
Tff7b72import T7ee787coil3.util.DebugLogger
Tff7b72import T7ee787io.ktor.client.HttpClient
Tff7b72import T7ee787kotlinx.coroutines.flow.first
Tff7b72import T7ee787okio.Path.Companion.toPath
Tff7b72import T7ee787org.jetbrains.compose.resources.decodeToSvgPainter
Tff7b72import T7ee787org.jetbrains.compose.resources.getString
Tff7b72import T7ee787org.jetbrains.compose.resources.stringResource
Tff7b72import T7ee787org.koin.compose.koinInject
Tff7b72import T7ee787org.koin.core.context.startKoin
Tff7b72import T7ee787org.koin.core.context.stopKoin
Tff7b72import T7ee787org.meshtastic.core.common.BuildConfigProvider
Tff7b72import T7ee787org.meshtastic.core.common.log.InMemoryLogBuffer
Tff7b72import T7ee787org.meshtastic.core.common.util.CommonUri
Tff7b72import T7ee787org.meshtastic.core.database.desktopDataDir
Tff7b72import T7ee787org.meshtastic.core.navigation.MultiBackstack
Tff7b72import T7ee787org.meshtastic.core.navigation.SettingsRoute
Tff7b72import T7ee787org.meshtastic.core.navigation.TopLevelDestination
Tff7b72import T7ee787org.meshtastic.core.navigation.rememberMultiBackstack
Tff7b72import T7ee787org.meshtastic.core.repository.Notification
Tff7b72import T7ee787org.meshtastic.core.repository.UiPrefs
Tff7b72import T7ee787org.meshtastic.core.resources.Res
Tff7b72import T7ee787org.meshtastic.core.resources.desktop_tray_quit
Tff7b72import T7ee787org.meshtastic.core.resources.desktop_tray_show
Tff7b72import T7ee787org.meshtastic.core.resources.desktop_tray_tooltip
Tff7b72import T7ee787org.meshtastic.core.resources.desktop_update_available_message
Tff7b72import T7ee787org.meshtastic.core.resources.desktop_update_available_title
Tff7b72import T7ee787org.meshtastic.core.resources.desktop_update_download
Tff7b72import T7ee787org.meshtastic.core.service.MeshServiceOrchestrator
Tff7b72import T7ee787org.meshtastic.core.ui.theme.AppTheme
Tff7b72import T7ee787org.meshtastic.core.ui.util.LocalEventBranding
Tff7b72import T7ee787org.meshtastic.core.ui.util.rememberOpenUrl
Tff7b72import T7ee787org.meshtastic.core.ui.viewmodel.UIViewModel
Tff7b72import T7ee787org.meshtastic.desktop.data.DesktopPreferencesDataSource
Tff7b72import T7ee787org.meshtastic.desktop.di.desktopModule
Tff7b72import T7ee787org.meshtastic.desktop.di.desktopPlatformModule
Tff7b72import T7ee787org.meshtastic.desktop.notification.DesktopOS
Tff7b72import T7ee787org.meshtastic.desktop.ui.DesktopMainScreen
Tff7b72import T7ee787java.awt.Desktop
Tff7b72import T7ee787java.util.Locale
Tff7b72import T7ee787kotlin.system.exitProcess
Tff7b72import T7ee787coil3.util.Logger Tff7b72as Te6edf3CoilLogger

T8b949e/** Meshtastic Desktop โ€” the first non-Android target for the shared KMP module graph. */
Tff7b72private Tff7b72const Tff7b72val Te6edf3MEMORY_CACHE_MAX_BYTES Tff7b72= T79c0ff6T79c0ff4L Tff7b72* T79c0ff1T79c0ff0T79c0ff2T79c0ff4L Tff7b72* T79c0ff1T79c0ff0T79c0ff2T79c0ff4L T8b949e// 64 MiB
Tff7b72private Tff7b72const Tff7b72val Te6edf3DISK_CACHE_MAX_BYTES Tff7b72= T79c0ff3T79c0ff2L Tff7b72* T79c0ff1T79c0ff0T79c0ff2T79c0ff4L Tff7b72* T79c0ff1T79c0ff0T79c0ff2T79c0ff4L T8b949e// 32 MiB

T8b949e/**
* Loads an SVG from JVM classpath resources and returns a [Painter].
*
* Uses the CMP 1.11 `decodeToSvgPainter` extension which replaces the deprecated `useResource`/`loadSvgPainter` pair.
* The SVG bytes are read from the classpath because CMP `composeResources/` only supports XML vector drawables and
* raster images โ€” not raw SVGs. Since the desktop module is a JVM-only host shell, classpath resource access is safe.
*/
Tf0883e@Composable
Tff7b72private Tff7b72fun Td2a8ffsvgPainterResourceTb4b4b4(Te6edf3pathTb4b4b4: Tffa657StringTb4b4b4, Te6edf3densityTb4b4b4: Te6edf3DensityTb4b4b4)Tb4b4b4: Te6edf3Painter Tff7b72= Te6edf3rememberTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3densityTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3classLoader Tff7b72=
Te6edf3requireNotNullTb4b4b4(Te6edf3ThreadTb4b4b4.Te6edf3currentThreadTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3contextClassLoaderTb4b4b4) Tb4b4b4{
Ta5d6ff"Ta5d6ffMissing context class loader while loading resource: Tffd700$Te6edf3pathTa5d6ff"
Tb4b4b4}
Tff7b72val Te6edf3bytes Tff7b72=
Te6edf3requireNotNullTb4b4b4(Te6edf3classLoaderTb4b4b4.Te6edf3getResourceAsStreamTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffMissing classpath resource: Tffd700$Te6edf3pathTa5d6ff" Tb4b4b4}
Tb4b4b4.Te6edf3use Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3readAllBytesTb4b4b4(Tb4b4b4) Tb4b4b4}
Te6edf3bytesTb4b4b4.Te6edf3decodeToSvgPainterTb4b4b4(Te6edf3densityTb4b4b4)
Tb4b4b4}

Tf0883e@OptInTb4b4b4(Te6edf3ExperimentalCoilApiTff7b72::Te6edf3classTb4b4b4)
Tff7b72fun Td2a8ffmainTb4b4b4(Te6edf3argsTb4b4b4: Te6edf3ArrayTff7b72<Tffa657StringTff7b72>Tb4b4b4) Tb4b4b4{
T8b949e// exitProcessOnExit = false is what makes the shutdown block below reachable at all: with the default (true),
T8b949e// application() calls System.exit(0) itself as soon as the Compose loop ends, and control never returns here.
T8b949e// Do not "simplify" this back to a bare application {} โ€” that silently disables every teardown that follows.
Te6edf3applicationTb4b4b4(Te6edf3exitProcessOnExit Tff7b72= Tff7b72falseTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3koinApp Tff7b72= Te6edf3remember Tb4b4b4{
T8b949e// Keep console output and also capture into the in-memory buffer the Debug screen views/exports.
Te6edf3LoggerTb4b4b4.Te6edf3setLogWritersTb4b4b4(Te6edf3listOfTb4b4b4(Te6edf3platformLogWriterTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3InMemoryLogBufferTb4b4b4)Tb4b4b4)
Te6edf3LoggerTb4b4b4.Te6edf3i Tb4b4b4{ Ta5d6ff"Ta5d6ffMeshtastic Desktop โ€” StartingTa5d6ff" Tb4b4b4}
Te6edf3startKoin Tb4b4b4{ Te6edf3modulesTb4b4b4(Te6edf3desktopPlatformModuleTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3desktopModuleTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72val Te6edf3systemLocale Tff7b72= Te6edf3remember Tb4b4b4{ Te6edf3LocaleTb4b4b4.Te6edf3getDefaultTb4b4b4(Tb4b4b4) Tb4b4b4}
Tff7b72val Te6edf3uiViewModel Tff7b72= Te6edf3remember Tb4b4b4{ Te6edf3koinAppTb4b4b4.Te6edf3koinTb4b4b4.Te6edf3getTff7b72<Te6edf3UIViewModelTff7b72>Tb4b4b4(Tb4b4b4) Tb4b4b4}
Tff7b72val Te6edf3httpClient Tff7b72= Te6edf3remember Tb4b4b4{ Te6edf3koinAppTb4b4b4.Te6edf3koinTb4b4b4.Te6edf3getTff7b72<Te6edf3HttpClientTff7b72>Tb4b4b4(Tb4b4b4) Tb4b4b4}

Te6edf3DeepLinkHandlerTb4b4b4(Te6edf3argsTb4b4b4, Te6edf3uiViewModelTb4b4b4)
Te6edf3MeshServiceLifecycleTb4b4b4(Tb4b4b4)
Te6edf3ThemeAndLocaleProviderTb4b4b4(Te6edf3uiViewModelTb4b4b4)
Tb4b4b4}

T8b949e// Runs on the main thread with the UI already gone. Closing the container fires the `onClose` callbacks that
T8b949e// release native handles โ€” currently libnotify's process-wide state in LinuxNotificationSender. Guarded because
T8b949e// a teardown failure must not turn a clean quit into a non-zero exit.
Te6edf3runCatching Tb4b4b4{ Te6edf3stopKoinTb4b4b4(Tb4b4b4) Tb4b4b4}Tb4b4b4.Te6edf3onFailure Tb4b4b4{ Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffstopKoin() failed during shutdownTa5d6ff" Tb4b4b4} Tb4b4b4}
Te6edf3LoggerTb4b4b4.Te6edf3i Tb4b4b4{ Ta5d6ff"Ta5d6ffMeshtastic Desktop โ€” StoppedTa5d6ff" Tb4b4b4}

T8b949e// Restores the exit application() no longer performs. Not optional: lingering non-daemon threads (coroutine
T8b949e// dispatchers, ktor pools, AWT stragglers) would otherwise keep the JVM alive after the last window closes,
T8b949e// turning "quit" into a hung background process.
Te6edf3exitProcessTb4b4b4(T79c0ff0Tb4b4b4)
Tb4b4b4}

T8b949e// ----- Deep link handling -----

T8b949e/** Processes deep-link URIs from CLI arguments and OS-level URI handlers. */
Tf0883e@Composable
Tff7b72private Tff7b72fun Te6edf3ApplicationScopeTb4b4b4.Td2a8ffDeepLinkHandlerTb4b4b4(Te6edf3argsTb4b4b4: Te6edf3ArrayTff7b72<Tffa657StringTff7b72>Tb4b4b4, Te6edf3uiViewModelTb4b4b4: Te6edf3UIViewModelTb4b4b4) Tb4b4b4{
Te6edf3LaunchedEffectTb4b4b4(Te6edf3argsTb4b4b4) Tb4b4b4{
Te6edf3argsTb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3arg Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(
Te6edf3argTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"Ta5d6ffmeshtastic://Ta5d6ff"Tb4b4b4) Tff7b72|Tff7b72|
Te6edf3argTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"Ta5d6ffhttp://meshtastic.orgTa5d6ff"Tb4b4b4) Tff7b72|Tff7b72|
Te6edf3argTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"Ta5d6ffhttps://meshtastic.orgTa5d6ff"Tb4b4b4)
Tb4b4b4) Tb4b4b4{
Te6edf3uiViewModelTb4b4b4.Te6edf3handleDeepLinkTb4b4b4(Te6edf3CommonUriTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3argTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3e Tb4b4b4{ Ta5d6ff"Ta5d6ffInvalid Meshtastic URI passed via args: Tffd700$Te6edf3argTa5d6ff" Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Te6edf3LaunchedEffectTb4b4b4(Tffa657UnitTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3DesktopTb4b4b4.Te6edf3isDesktopSupportedTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3DesktopTb4b4b4.Te6edf3getDesktopTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3isSupportedTb4b4b4(Te6edf3DesktopTb4b4b4.Te6edf3ActionTb4b4b4.Te6edf3APP_OPEN_URITb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3DesktopTb4b4b4.Te6edf3getDesktopTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3setOpenURIHandler Tb4b4b4{ Te6edf3event Tff7b72-Tff7b72>
Tff7b72val Te6edf3uriStr Tff7b72= Te6edf3eventTb4b4b4.Te6edf3uriTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)
Te6edf3uiViewModelTb4b4b4.Te6edf3handleDeepLinkTb4b4b4(Te6edf3CommonUriTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3uriStrTb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3LoggerTb4b4b4.Te6edf3e Tb4b4b4{ Ta5d6ff"Ta5d6ffInvalid URI from OS: Tffd700$Te6edf3uriStrTa5d6ff" Tb4b4b4} Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

T8b949e// ----- Mesh service lifecycle -----

T8b949e/** Starts [MeshServiceOrchestrator] on composition and stops it on disposal. */
Tf0883e@Composable
Tff7b72private Tff7b72fun Td2a8ffMeshServiceLifecycleTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3meshServiceController Tff7b72= Te6edf3koinInjectTff7b72<Te6edf3MeshServiceOrchestratorTff7b72>Tb4b4b4(Tb4b4b4)
Te6edf3DisposableEffectTb4b4b4(Tffa657UnitTb4b4b4) Tb4b4b4{
Te6edf3meshServiceControllerTb4b4b4.Te6edf3startTb4b4b4(Tb4b4b4)
Te6edf3onDispose Tb4b4b4{ Te6edf3meshServiceControllerTb4b4b4.Te6edf3stopTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

T8b949e// ----- Theme, locale, and application shell -----

T8b949e/** Resolves the user's theme/locale preferences and renders the full application UI. */
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffViewModelForwardingTa5d6ff"Tb4b4b4)
Tf0883e@Composable
Tf0883e@OptInTb4b4b4(Te6edf3ExperimentalCoilApiTff7b72::Te6edf3classTb4b4b4)
Tff7b72private Tff7b72fun Te6edf3ApplicationScopeTb4b4b4.Td2a8ffThemeAndLocaleProviderTb4b4b4(Te6edf3uiViewModelTb4b4b4: Te6edf3UIViewModelTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3systemLocale Tff7b72= Te6edf3remember Tb4b4b4{ Te6edf3LocaleTb4b4b4.Te6edf3getDefaultTb4b4b4(Tb4b4b4) Tb4b4b4}
Tff7b72val Te6edf3uiPrefs Tff7b72= Te6edf3koinInjectTff7b72<Te6edf3UiPrefsTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3themePref Tff7b72by Te6edf3uiPrefsTb4b4b4.Te6edf3themeTb4b4b4.Te6edf3collectAsStateTb4b4b4(Te6edf3initial Tff7b72= Tff7b72-T79c0ff1Tb4b4b4)
Tff7b72val Te6edf3localePref Tff7b72by Te6edf3uiPrefsTb4b4b4.Te6edf3localeTb4b4b4.Te6edf3collectAsStateTb4b4b4(Te6edf3initial Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4)
Te6edf3LocaleTb4b4b4.Te6edf3setDefaultTb4b4b4(Te6edf3localePrefTb4b4b4.Te6edf3takeIf Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4) Tb4b4b4}Tff7b72?.Te6edf3letTb4b4b4(Te6edf3LocaleTff7b72::Te6edf3forLanguageTagTb4b4b4) Tff7b72?: Te6edf3systemLocaleTb4b4b4)

Tff7b72val Te6edf3isDarkTheme Tff7b72=
Tff7b72when Tb4b4b4(Te6edf3themePrefTb4b4b4) Tb4b4b4{
T79c0ff1 Tff7b72-Tff7b72> Tff7b72false
T79c0ff2 Tff7b72-Tff7b72> Tff7b72true
Tff7b72else Tff7b72-Tff7b72> Te6edf3isSystemInDarkThemeTb4b4b4(Tb4b4b4)
Tb4b4b4}

Te6edf3MeshtasticDesktopAppTb4b4b4(Te6edf3uiViewModelTb4b4b4, Te6edf3isDarkThemeTb4b4b4)
Tb4b4b4}

T8b949e// ----- Application chrome (tray, window, navigation) -----

T8b949e/** Composes the system tray, window, and Coil image loader. */
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffViewModelForwardingTa5d6ff"Tb4b4b4)
Tf0883e@Composable
Tf0883e@OptInTb4b4b4(Te6edf3ExperimentalCoilApiTff7b72::Te6edf3classTb4b4b4)
Tff7b72private Tff7b72fun Te6edf3ApplicationScopeTb4b4b4.Td2a8ffMeshtasticDesktopAppTb4b4b4(Te6edf3uiViewModelTb4b4b4: Te6edf3UIViewModelTb4b4b4, Te6edf3isDarkThemeTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Tff7b72var Te6edf3isAppVisible Tff7b72by Te6edf3remember Tb4b4b4{ Te6edf3mutableStateOfTb4b4b4(Tff7b72trueTb4b4b4) Tb4b4b4}
Tff7b72var Te6edf3isWindowReady Tff7b72by Te6edf3remember Tb4b4b4{ Te6edf3mutableStateOfTb4b4b4(Tff7b72falseTb4b4b4) Tb4b4b4}
Tff7b72val Te6edf3trayState Tff7b72= Te6edf3rememberTrayStateTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3density Tff7b72= Te6edf3LocalDensityTb4b4b4.Te6edf3current
Tff7b72val Te6edf3appIcon Tff7b72= Te6edf3svgPainterResourceTb4b4b4(Ta5d6ff"Ta5d6fftray_icon_black.svgTa5d6ff"Tb4b4b4, Te6edf3densityTb4b4b4)

Tff7b72val Te6edf3trayIcon Tff7b72=
Te6edf3svgPainterResourceTb4b4b4(Tff7b72if Tb4b4b4(Te6edf3isSystemInDarkThemeTb4b4b4(Tb4b4b4)Tb4b4b4) Ta5d6ff"Ta5d6fftray_icon_white.svgTa5d6ff" Tff7b72else Ta5d6ff"Ta5d6fftray_icon_black.svgTa5d6ff"Tb4b4b4, Te6edf3densityTb4b4b4)

Tff7b72val Te6edf3notificationManager Tff7b72= Te6edf3koinInjectTff7b72<Te6edf3DesktopNotificationManagerTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3desktopPrefs Tff7b72= Te6edf3koinInjectTff7b72<Te6edf3DesktopPreferencesDataSourceTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3windowState Tff7b72= Te6edf3rememberWindowStateTb4b4b4(Tb4b4b4)

Te6edf3LaunchedEffectTb4b4b4(Tffa657UnitTb4b4b4) Tb4b4b4{
Te6edf3notificationManagerTb4b4b4.Te6edf3fallbackNotificationsTb4b4b4.Te6edf3collect Tb4b4b4{ Te6edf3notification Tff7b72-Tff7b72> Te6edf3trayStateTb4b4b4.Te6edf3sendNotificationTb4b4b4(Te6edf3notificationTb4b4b4) Tb4b4b4}
Tb4b4b4}

Tff7b72val Te6edf3openUrl Tff7b72= Te6edf3rememberOpenUrlTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3updateInfo Tff7b72= Te6edf3rememberAvailableUpdateTb4b4b4(Te6edf3notificationManagerTb4b4b4)

Te6edf3WindowBoundsManagerTb4b4b4(Te6edf3desktopPrefsTb4b4b4, Te6edf3windowStateTb4b4b4) Tb4b4b4{ Te6edf3isWindowReady Tff7b72= Tff7b72true Tb4b4b4}

Te6edf3TrayTb4b4b4(
Te6edf3state Tff7b72= Te6edf3trayStateTb4b4b4,
Te6edf3icon Tff7b72= Te6edf3trayIconTb4b4b4,
Te6edf3tooltip Tff7b72= Te6edf3stringResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3desktop_tray_tooltipTb4b4b4)Tb4b4b4,
Te6edf3onAction Tff7b72= Tb4b4b4{ Te6edf3isAppVisible Tff7b72= Tff7b72true Tb4b4b4}Tb4b4b4,
Te6edf3menu Tff7b72= Tb4b4b4{
Te6edf3updateInfoTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3update Tff7b72-Tff7b72>
Te6edf3ItemTb4b4b4(
Te6edf3stringResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3desktop_update_downloadTb4b4b4, Te6edf3updateTb4b4b4.Te6edf3versionNameTb4b4b4)Tb4b4b4,
Te6edf3onClick Tff7b72= Tb4b4b4{ Te6edf3openUrlTb4b4b4(Te6edf3updateTb4b4b4.Te6edf3releaseUrlTb4b4b4) Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3ItemTb4b4b4(Te6edf3stringResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3desktop_tray_showTb4b4b4)Tb4b4b4, Te6edf3onClick Tff7b72= Tb4b4b4{ Te6edf3isAppVisible Tff7b72= Tff7b72true Tb4b4b4}Tb4b4b4)
Te6edf3ItemTb4b4b4(Te6edf3stringResourceTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3desktop_tray_quitTb4b4b4)Tb4b4b4, Te6edf3onClick Tff7b72= Tff7b72::Te6edf3exitApplicationTb4b4b4)
Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Tff7b72if Tb4b4b4(Te6edf3isWindowReadyTb4b4b4) Tb4b4b4{
T8b949e// Hide via `visible` rather than dropping the Window from composition so the UI tree
T8b949e// (navigation backstack, scroll positions) survives a hide-to-tray round trip.
Te6edf3MeshtasticWindowTb4b4b4(Te6edf3uiViewModelTb4b4b4, Te6edf3isDarkThemeTb4b4b4, Te6edf3appIconTb4b4b4, Te6edf3windowStateTb4b4b4, Te6edf3visible Tff7b72= Te6edf3isAppVisibleTb4b4b4) Tb4b4b4{
T8b949e// Minimize to the tray on close โ€” but only where a tray exists. On platforms without a
T8b949e// system tray (e.g. some Linux desktop environments) there's nowhere to minimize to, so
T8b949e// quit instead; otherwise the process would be stranded with no window and no tray icon.
Tff7b72if Tb4b4b4(Te6edf3isTraySupportedTb4b4b4) Tb4b4b4{
Te6edf3isAppVisible Tff7b72= Tff7b72false
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3exitApplicationTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

T8b949e// ----- Update discovery -----

T8b949e/**
* Checks once per launch whether a newer release is published on GitHub and surfaces it via a native notification.
* Release builds only โ€” dev builds carry the bare base version and would match or trail every published release.
* Flatpak installs (FLATPAK_ID is set inside the sandbox) update through Flathub instead, so don't point them at
* GitHub.
*/
Tf0883e@Composable
Tff7b72private Tff7b72fun Td2a8ffrememberAvailableUpdateTb4b4b4(Te6edf3notificationManagerTb4b4b4: Te6edf3DesktopNotificationManagerTb4b4b4)Tb4b4b4: Te6edf3UpdateCheckerTb4b4b4.Te6edf3UpdateInfoTff7b72? Tb4b4b4{
Tff7b72val Te6edf3buildConfig Tff7b72= Te6edf3koinInjectTff7b72<Te6edf3BuildConfigProviderTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3httpClient Tff7b72= Te6edf3koinInjectTff7b72<Te6edf3HttpClientTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3updateInfo Tff7b72by
Te6edf3produceStateTff7b72<Te6edf3UpdateCheckerTb4b4b4.Te6edf3UpdateInfoTff7b72?Tff7b72>Tb4b4b4(Te6edf3initialValue Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3buildConfigTb4b4b4.Te6edf3isDebug Tff7b72&Tff7b72& Te6edf3SystemTb4b4b4.Te6edf3getenvTb4b4b4(Ta5d6ff"Ta5d6ffFLATPAK_IDTa5d6ff"Tb4b4b4) Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3value Tff7b72= Te6edf3UpdateCheckerTb4b4b4(Te6edf3httpClientTb4b4b4)Tb4b4b4.Te6edf3checkTb4b4b4(Te6edf3buildConfigTb4b4b4.Te6edf3versionNameTb4b4b4)
Tb4b4b4}
Tb4b4b4}

Te6edf3LaunchedEffectTb4b4b4(Te6edf3updateInfoTb4b4b4) Tb4b4b4{
Te6edf3updateInfoTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3update Tff7b72-Tff7b72>
Te6edf3notificationManagerTb4b4b4.Te6edf3dispatchTb4b4b4(
Te6edf3NotificationTb4b4b4(
Te6edf3title Tff7b72= Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3desktop_update_available_titleTb4b4b4)Tb4b4b4,
Te6edf3message Tff7b72= Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3desktop_update_available_messageTb4b4b4, Te6edf3updateTb4b4b4.Te6edf3versionNameTb4b4b4)Tb4b4b4,
Te6edf3category Tff7b72= Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3ServiceTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72return Te6edf3updateInfo
Tb4b4b4}

T8b949e// ----- Window bounds persistence -----

T8b949e/** Restores window geometry from preferences and persists changes via [snapshotFlow]. */
Tf0883e@Composable
Tff7b72private Tff7b72fun Td2a8ffWindowBoundsManagerTb4b4b4(
Te6edf3desktopPrefsTb4b4b4: Te6edf3DesktopPreferencesDataSourceTb4b4b4,
Te6edf3windowStateTb4b4b4: Te6edf3WindowStateTb4b4b4,
Te6edf3onReadyTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3LaunchedEffectTb4b4b4(Tffa657UnitTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3initialWidth Tff7b72= Te6edf3desktopPrefsTb4b4b4.Te6edf3windowWidthTb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3initialHeight Tff7b72= Te6edf3desktopPrefsTb4b4b4.Te6edf3windowHeightTb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3initialX Tff7b72= Te6edf3desktopPrefsTb4b4b4.Te6edf3windowXTb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3initialY Tff7b72= Te6edf3desktopPrefsTb4b4b4.Te6edf3windowYTb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)

Te6edf3windowStateTb4b4b4.Te6edf3size Tff7b72= Te6edf3DpSizeTb4b4b4(Te6edf3initialWidthTb4b4b4.Te6edf3dpTb4b4b4, Te6edf3initialHeightTb4b4b4.Te6edf3dpTb4b4b4)
Te6edf3windowStateTb4b4b4.Te6edf3position Tff7b72=
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3initialXTb4b4b4.Te6edf3isNaNTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Tff7b72!Te6edf3initialYTb4b4b4.Te6edf3isNaNTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3WindowPositionTb4b4b4(Te6edf3initialXTb4b4b4.Te6edf3dpTb4b4b4, Te6edf3initialYTb4b4b4.Te6edf3dpTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3WindowPositionTb4b4b4(Te6edf3AlignmentTb4b4b4.Te6edf3CenterTb4b4b4)
Tb4b4b4}

Te6edf3onReadyTb4b4b4(Tb4b4b4)

Te6edf3snapshotFlow Tb4b4b4{
Tff7b72val Te6edf3x Tff7b72= Tff7b72if Tb4b4b4(Te6edf3windowStateTb4b4b4.Te6edf3positionTb4b4b4.Te6edf3isSpecifiedTb4b4b4) Te6edf3windowStateTb4b4b4.Te6edf3positionTb4b4b4.Te6edf3xTb4b4b4.Te6edf3value Tff7b72else Tffa657FloatTb4b4b4.Te6edf3NaN
Tff7b72val Te6edf3y Tff7b72= Tff7b72if Tb4b4b4(Te6edf3windowStateTb4b4b4.Te6edf3positionTb4b4b4.Te6edf3isSpecifiedTb4b4b4) Te6edf3windowStateTb4b4b4.Te6edf3positionTb4b4b4.Te6edf3yTb4b4b4.Te6edf3value Tff7b72else Tffa657FloatTb4b4b4.Te6edf3NaN
Te6edf3listOfTb4b4b4(Te6edf3windowStateTb4b4b4.Te6edf3sizeTb4b4b4.Te6edf3widthTb4b4b4.Te6edf3valueTb4b4b4, Te6edf3windowStateTb4b4b4.Te6edf3sizeTb4b4b4.Te6edf3heightTb4b4b4.Te6edf3valueTb4b4b4, Te6edf3xTb4b4b4, Te6edf3yTb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3collect Tb4b4b4{ Te6edf3bounds Tff7b72-Tff7b72>
Te6edf3desktopPrefsTb4b4b4.Te6edf3setWindowBoundsTb4b4b4(Te6edf3width Tff7b72= Te6edf3boundsTff7b72[T79c0ff0Tff7b72]Tb4b4b4, Te6edf3height Tff7b72= Te6edf3boundsTff7b72[T79c0ff1Tff7b72]Tb4b4b4, Te6edf3x Tff7b72= Te6edf3boundsTff7b72[T79c0ff2Tff7b72]Tb4b4b4, Te6edf3y Tff7b72= Te6edf3boundsTff7b72[T79c0ff3Tff7b72]Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

T8b949e// ----- Main window with keyboard shortcuts and Coil -----

T8b949e/** Renders the main application window with keyboard shortcuts, Coil image loading, and the Compose UI tree. */
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffViewModelForwardingTa5d6ff"Tb4b4b4)
Tf0883e@Composable
Tf0883e@OptInTb4b4b4(Te6edf3ExperimentalCoilApiTff7b72::Te6edf3classTb4b4b4)
Tff7b72private Tff7b72fun Te6edf3ApplicationScopeTb4b4b4.Td2a8ffMeshtasticWindowTb4b4b4(
Te6edf3uiViewModelTb4b4b4: Te6edf3UIViewModelTb4b4b4,
Te6edf3isDarkThemeTb4b4b4: Tffa657BooleanTb4b4b4,
Te6edf3appIconTb4b4b4: Te6edf3PainterTb4b4b4,
Te6edf3windowStateTb4b4b4: Te6edf3WindowStateTb4b4b4,
Te6edf3visibleTb4b4b4: Tffa657BooleanTb4b4b4,
Te6edf3onCloseRequestTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4,
Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3multiBackstack Tff7b72=
Te6edf3rememberMultiBackstackTb4b4b4(
T8b949e// Land on Connections for first-run / no-device-selected; otherwise on Nodes.
Tff7b72if Tb4b4b4(Te6edf3uiViewModelTb4b4b4.Te6edf3currentDeviceAddressFlowTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3let Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3isNullOrBlankTb4b4b4(Tb4b4b4) Tff7b72|Tff7b72| Tffa657it Tff7b72=Tff7b72= Ta5d6ff"Ta5d6ffnTa5d6ff" Tb4b4b4}Tb4b4b4) Tb4b4b4{
Te6edf3TopLevelDestinationTb4b4b4.Te6edf3ConnectTb4b4b4.Te6edf3route
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3TopLevelDestinationTb4b4b4.Te6edf3NodesTb4b4b4.Te6edf3route
Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Te6edf3WindowTb4b4b4(
Te6edf3onCloseRequest Tff7b72= Te6edf3onCloseRequestTb4b4b4,
Te6edf3title Tff7b72= Ta5d6ff"Ta5d6ffMeshtastic DesktopTa5d6ff"Tb4b4b4,
Te6edf3icon Tff7b72= Te6edf3appIconTb4b4b4,
Te6edf3state Tff7b72= Te6edf3windowStateTb4b4b4,
Te6edf3visible Tff7b72= Te6edf3visibleTb4b4b4,
Te6edf3onPreviewKeyEvent Tff7b72= Tb4b4b4{ Te6edf3event Tff7b72-Tff7b72> Te6edf3handleKeyboardShortcutTb4b4b4(Te6edf3eventTb4b4b4, Te6edf3multiBackstackTb4b4b4, Tff7b72::Te6edf3exitApplicationTb4b4b4) Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3eventEdition Tff7b72by Te6edf3uiViewModelTb4b4b4.Te6edf3eventEditionTb4b4b4.Te6edf3collectAsStateTb4b4b4(Tb4b4b4)

Te6edf3CoilImageLoaderSetupTb4b4b4(Tb4b4b4)
Te6edf3CompositionLocalProviderTb4b4b4(Te6edf3LocalEventBranding Te6edf3provides Te6edf3eventEditionTb4b4b4) Tb4b4b4{
Te6edf3AppThemeTb4b4b4(Te6edf3darkTheme Tff7b72= Te6edf3isDarkThemeTb4b4b4) Tb4b4b4{ Te6edf3DesktopMainScreenTb4b4b4(Te6edf3uiViewModelTb4b4b4, Te6edf3multiBackstackTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

T8b949e/** Configures the Coil singleton [ImageLoader] with Ktor networking, SVG decoding, and caching. */
Tf0883e@Composable
Tf0883e@OptInTb4b4b4(Te6edf3ExperimentalCoilApiTff7b72::Te6edf3classTb4b4b4)
Tff7b72private Tff7b72fun Td2a8ffCoilImageLoaderSetupTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3httpClient Tff7b72= Te6edf3koinInjectTff7b72<Te6edf3HttpClientTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3buildConfigProvider Tff7b72= Te6edf3koinInjectTff7b72<Te6edf3BuildConfigProviderTff7b72>Tb4b4b4(Tb4b4b4)

Te6edf3setSingletonImageLoaderFactory Tb4b4b4{ Te6edf3context Tff7b72-Tff7b72>
Tff7b72val Te6edf3cacheDir Tff7b72= Te6edf3desktopDataDirTb4b4b4(Tb4b4b4) Tff7b72+ Ta5d6ff"Ta5d6ff/image_cache_v3Ta5d6ff"
Te6edf3ImageLoaderTb4b4b4.Te6edf3BuilderTb4b4b4(Te6edf3contextTb4b4b4)
Tb4b4b4.Te6edf3components Tb4b4b4{
Te6edf3addTb4b4b4(
Te6edf3KtorNetworkFetcherFactoryTb4b4b4(
Te6edf3httpClient Tff7b72= Te6edf3httpClientTb4b4b4,
Te6edf3concurrentRequestStrategy Tff7b72= Te6edf3DeDupeConcurrentRequestStrategyTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
T8b949e// Render SVGs to a bitmap on Desktop to avoid Skiko vector rendering artifacts
T8b949e// that show up as solid/black hardware images.
Te6edf3addTb4b4b4(Te6edf3SvgDecoderTb4b4b4.Te6edf3FactoryTb4b4b4(Te6edf3renderToBitmap Tff7b72= Tff7b72trueTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3memoryCache Tb4b4b4{ Te6edf3MemoryCacheTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3maxSizeBytesTb4b4b4(Te6edf3MEMORY_CACHE_MAX_BYTESTb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4.Te6edf3diskCache Tb4b4b4{ Te6edf3DiskCacheTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3directoryTb4b4b4(Te6edf3cacheDirTb4b4b4.Te6edf3toPathTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3maxSizeBytesTb4b4b4(Te6edf3DISK_CACHE_MAX_BYTESTb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4.Te6edf3loggerTb4b4b4(Tff7b72if Tb4b4b4(Te6edf3buildConfigProviderTb4b4b4.Te6edf3isDebugTb4b4b4) Te6edf3DebugLoggerTb4b4b4(Te6edf3minLevel Tff7b72= Te6edf3CoilLoggerTb4b4b4.Te6edf3LevelTb4b4b4.Te6edf3VerboseTb4b4b4) Tff7b72else Tff7b72nullTb4b4b4)
Tb4b4b4.Te6edf3crossfadeTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

T8b949e// ----- Keyboard shortcuts -----

Tff7b72private Tff7b72val Te6edf3isMacOS Tff7b72= Te6edf3DesktopOSTb4b4b4.Te6edf3currentTb4b4b4(Tb4b4b4) Tff7b72=Tff7b72= Te6edf3DesktopOSTb4b4b4.Te6edf3MacOS

T8b949e/**
* Platform-conventional shortcut modifier: Cmd on macOS, Ctrl on Windows/Linux. Alt must be up on the Ctrl path because
* Windows reports AltGr as Ctrl+Alt โ€” otherwise typing AltGr characters (e.g. @ on German layouts, which is AltGr+Q)
* would trigger shortcuts like quit.
*/
Tff7b72private Tff7b72val Te6edf3KeyEventTb4b4b4.Te6edf3isShortcutModifierPressedTb4b4b4: Tffa657Boolean
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Tff7b72if Tb4b4b4(Te6edf3isMacOSTb4b4b4) Te6edf3isMetaPressed Tff7b72else Te6edf3isCtrlPressed Tff7b72&Tff7b72& Tff7b72!Te6edf3isAltPressed

T8b949e/** Handles Cmd/Ctrl-key shortcuts. Returns `true` if the event was consumed. */
Tff7b72private Tff7b72fun Td2a8ffhandleKeyboardShortcutTb4b4b4(
Te6edf3eventTb4b4b4: Te6edf3KeyEventTb4b4b4,
Te6edf3multiBackstackTb4b4b4: Te6edf3MultiBackstackTb4b4b4,
Te6edf3exitApplicationTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4,
Tb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3eventTb4b4b4.Te6edf3type Tff7b72!Tff7b72= Te6edf3KeyEventTypeTb4b4b4.Te6edf3KeyDown Tff7b72|Tff7b72| Tff7b72!Te6edf3eventTb4b4b4.Te6edf3isShortcutModifierPressedTb4b4b4) Tff7b72return Tff7b72false
Tff7b72val Te6edf3backStack Tff7b72= Te6edf3multiBackstackTb4b4b4.Te6edf3activeBackStack
Tff7b72return Tff7b72when Tb4b4b4(Te6edf3eventTb4b4b4.Te6edf3keyTb4b4b4) Tb4b4b4{
Te6edf3KeyTb4b4b4.Te6edf3Q Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3exitApplicationTb4b4b4(Tb4b4b4)
Tff7b72true
Tb4b4b4}

Te6edf3KeyTb4b4b4.Te6edf3Comma Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3TopLevelDestinationTb4b4b4.Te6edf3Settings Tff7b72!Tff7b72= Te6edf3TopLevelDestinationTb4b4b4.Te6edf3fromNavKeyTb4b4b4(Te6edf3backStackTb4b4b4.Te6edf3lastOrNullTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3multiBackstackTb4b4b4.Te6edf3navigateTopLevelTb4b4b4(Te6edf3TopLevelDestinationTb4b4b4.Te6edf3SettingsTb4b4b4.Te6edf3routeTb4b4b4)
Tb4b4b4}
Tff7b72true
Tb4b4b4}

Te6edf3KeyTb4b4b4.Te6edf3One Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3multiBackstackTb4b4b4.Te6edf3navigateTopLevelTb4b4b4(Te6edf3TopLevelDestinationTb4b4b4.Te6edf3MessagesTb4b4b4.Te6edf3routeTb4b4b4)
Tff7b72true
Tb4b4b4}

Te6edf3KeyTb4b4b4.Te6edf3Two Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3multiBackstackTb4b4b4.Te6edf3navigateTopLevelTb4b4b4(Te6edf3TopLevelDestinationTb4b4b4.Te6edf3NodesTb4b4b4.Te6edf3routeTb4b4b4)
Tff7b72true
Tb4b4b4}

Te6edf3KeyTb4b4b4.Te6edf3Three Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3multiBackstackTb4b4b4.Te6edf3navigateTopLevelTb4b4b4(Te6edf3TopLevelDestinationTb4b4b4.Te6edf3MapTb4b4b4.Te6edf3routeTb4b4b4)
Tff7b72true
Tb4b4b4}

Te6edf3KeyTb4b4b4.Te6edf3Four Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3multiBackstackTb4b4b4.Te6edf3navigateTopLevelTb4b4b4(Te6edf3TopLevelDestinationTb4b4b4.Te6edf3ConnectTb4b4b4.Te6edf3routeTb4b4b4)
Tff7b72true
Tb4b4b4}

Te6edf3KeyTb4b4b4.Te6edf3Slash Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3backStackTb4b4b4.Te6edf3addTb4b4b4(Te6edf3SettingsRouteTb4b4b4.Te6edf3AboutTb4b4b4)
Tff7b72true
Tb4b4b4}

Tff7b72else Tff7b72-Tff7b72> Tff7b72false
Tb4b4b4}
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.14s